/**
 * Copyright (c) 2008, Gaudenz Alder
 */
package com.mxgraph.swing.util;

import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.view.mxGraph;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;

/**
 * The type Mx graph actions.
 */
public class mxGraphActions {

    /**
     * The constant deleteAction.
     */
    static final Action deleteAction = new DeleteAction("delete");

    /**
     * The constant editAction.
     */
    static final Action editAction = new EditAction("edit");

    /**
     * The constant groupAction.
     */
    static final Action groupAction = new GroupAction("group");

    /**
     * The constant ungroupAction.
     */
    static final Action ungroupAction = new UngroupAction("ungroup");

    /**
     * The constant removeFromParentAction.
     */
    static final Action removeFromParentAction = new RemoveFromParentAction(
            "removeFromParent");

    /**
     * The constant updateGroupBoundsAction.
     */
    static final Action updateGroupBoundsAction = new UpdateGroupBoundsAction(
            "updateGroupBounds");

    /**
     * The constant selectAllAction.
     */
    static final Action selectAllAction = new SelectAction("selectAll");

    /**
     * The constant selectVerticesAction.
     */
    static final Action selectVerticesAction = new SelectAction("vertices");

    /**
     * The constant selectEdgesAction.
     */
    static final Action selectEdgesAction = new SelectAction("edges");

    /**
     * The constant selectNoneAction.
     */
    static final Action selectNoneAction = new SelectAction("selectNone");

    /**
     * The constant selectNextAction.
     */
    static final Action selectNextAction = new SelectAction("selectNext");

    /**
     * The constant selectPreviousAction.
     */
    static final Action selectPreviousAction = new SelectAction(
            "selectPrevious");

    /**
     * The constant selectParentAction.
     */
    static final Action selectParentAction = new SelectAction("selectParent");

    /**
     * The constant selectChildAction.
     */
    static final Action selectChildAction = new SelectAction("selectChild");

    /**
     * The constant collapseAction.
     */
    static final Action collapseAction = new FoldAction("collapse");

    /**
     * The constant expandAction.
     */
    static final Action expandAction = new FoldAction("expand");

    /**
     * The constant enterGroupAction.
     */
    static final Action enterGroupAction = new DrillAction("enterGroup");

    /**
     * The constant exitGroupAction.
     */
    static final Action exitGroupAction = new DrillAction("exitGroup");

    /**
     * The constant homeAction.
     */
    static final Action homeAction = new DrillAction("home");

    /**
     * The constant zoomActualAction.
     */
    static final Action zoomActualAction = new ZoomAction("actual");

    /**
     * The constant zoomInAction.
     */
    static final Action zoomInAction = new ZoomAction("zoomIn");

    /**
     * The constant zoomOutAction.
     */
    static final Action zoomOutAction = new ZoomAction("zoomOut");

    /**
     * The constant toBackAction.
     */
    static final Action toBackAction = new LayerAction("toBack");

    /**
     * The constant toFrontAction.
     */
    static final Action toFrontAction = new LayerAction("toFront");

    static final ConnectableAction connectableAction = new ConnectableAction("Connectable");

    /**
     * Gets delete action.
     *
     * @return the delete action
     */
    public static Action getDeleteAction() {
        return deleteAction;
    }

    /**
     * Gets edit action.
     *
     * @return the edit action
     */
    public static Action getEditAction() {
        return editAction;
    }

    /**
     * Gets group action.
     *
     * @return the edit action
     */
    public static Action getGroupAction() {
        return groupAction;
    }

    /**
     * Gets ungroup action.
     *
     * @return the edit action
     */
    public static Action getUngroupAction() {
        return ungroupAction;
    }

    /**
     * Gets remove from parent action.
     *
     * @return the edit action
     */
    public static Action getRemoveFromParentAction() {
        return removeFromParentAction;
    }

    /**
     * Gets update group bounds action.
     *
     * @return the edit action
     */
    public static Action getUpdateGroupBoundsAction() {
        return updateGroupBoundsAction;
    }

    /**
     * Gets select all action.
     *
     * @return the select all action
     */
    public static Action getSelectAllAction() {
        return selectAllAction;
    }

    /**
     * Gets select vertices action.
     *
     * @return the select vertices action
     */
    public static Action getSelectVerticesAction() {
        return selectVerticesAction;
    }

    /**
     * Gets select edges action.
     *
     * @return the select edges action
     */
    public static Action getSelectEdgesAction() {
        return selectEdgesAction;
    }

    /**
     * Gets select none action.
     *
     * @return the select none action
     */
    public static Action getSelectNoneAction() {
        return selectNoneAction;
    }

    /**
     * Gets select next action.
     *
     * @return the select next action
     */
    public static Action getSelectNextAction() {
        return selectNextAction;
    }

    /**
     * Gets select previous action.
     *
     * @return the select previous action
     */
    public static Action getSelectPreviousAction() {
        return selectPreviousAction;
    }

    /**
     * Gets select parent action.
     *
     * @return the select parent action
     */
    public static Action getSelectParentAction() {
        return selectParentAction;
    }

    /**
     * Gets select child action.
     *
     * @return the select child action
     */
    public static Action getSelectChildAction() {
        return selectChildAction;
    }

    /**
     * Gets enter group action.
     *
     * @return the go into action
     */
    public static Action getEnterGroupAction() {
        return enterGroupAction;
    }

    /**
     * Gets exit group action.
     *
     * @return the go up action
     */
    public static Action getExitGroupAction() {
        return exitGroupAction;
    }

    /**
     * Gets home action.
     *
     * @return the home action
     */
    public static Action getHomeAction() {
        return homeAction;
    }

    /**
     * Gets collapse action.
     *
     * @return the collapse action
     */
    public static Action getCollapseAction() {
        return collapseAction;
    }

    /**
     * Gets expand action.
     *
     * @return the expand action
     */
    public static Action getExpandAction() {
        return expandAction;
    }

    /**
     * Gets zoom actual action.
     *
     * @return the zoom actual action
     */
    public static Action getZoomActualAction() {
        return zoomActualAction;
    }

    /**
     * Gets zoom in action.
     *
     * @return the zoom in action
     */
    public static Action getZoomInAction() {
        return zoomInAction;
    }

    /**
     * Gets zoom out action.
     *
     * @return the zoom out action
     */
    public static Action getZoomOutAction() {
        return zoomOutAction;
    }

    /**
     * Gets to back action.
     *
     * @return the action that moves cell(s) to the backmost layer
     */
    public static Action getToBackAction() {
        return toBackAction;
    }

    /**
     * Gets to front action.
     *
     * @return the action that moves cell(s) to the frontmost layer
     */
    public static Action getToFrontAction() {
        return toFrontAction;
    }

    public static ConnectableAction getConnectableAction() {
        return connectableAction;
    }

    /**
     * Gets graph.
     *
     * @param e the e
     * @return Returns the graph for the given action event.
     */
    public static final mxGraph getGraph(ActionEvent e) {
        Object source = e.getSource();

        if (source instanceof mxGraphComponent) {
            return ((mxGraphComponent) source).getGraph();
        }

        return null;
    }

    /**
     * The type Edit action.
     */
    public static class EditAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = 4610112721356742702L;

        /**
         * Instantiates a new Edit action.
         *
         * @param name the name
         */
        public EditAction(String name) {
            super(name);
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                ((mxGraphComponent) e.getSource()).startEditing();
            }
        }

    }

    /**
     * The type Delete action.
     */
    public static class DeleteAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = -8212339796803275529L;

        /**
         * Instantiates a new Delete action.
         *
         * @param name the name
         */
        public DeleteAction(String name) {
            super(name);
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            mxGraph graph = getGraph(e);

            if (graph != null) {
                graph.removeCells();
            }
        }

    }

    /**
     * The type Group action.
     */
    public static class GroupAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = -4718086600089409092L;

        /**
         * Instantiates a new Group action.
         *
         * @param name the name
         */
        public GroupAction(String name) {
            super(name);
        }

        /**
         * Gets group border.
         *
         * @param graph the graph
         * @return the group border
         */
        protected int getGroupBorder(mxGraph graph) {
            return 2 * graph.getGridSize();

        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            mxGraph graph = getGraph(e);

            if (graph != null) {
                graph.setSelectionCell(graph.groupCells(null,
                        getGroupBorder(graph)));
            }
        }

    }

    /**
     * The type Ungroup action.
     */
    public static class UngroupAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = 2247770767961318251L;

        /**
         * Instantiates a new Ungroup action.
         *
         * @param name the name
         */
        public UngroupAction(String name) {
            super(name);
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            mxGraph graph = getGraph(e);

            if (graph != null) {
                graph.setSelectionCells(graph.ungroupCells());
            }
        }

    }

    /**
     * The type Remove from parent action.
     */
    public static class RemoveFromParentAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = 7169443038859140811L;

        /**
         * Instantiates a new Remove from parent action.
         *
         * @param name the name
         */
        public RemoveFromParentAction(String name) {
            super(name);
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            mxGraph graph = getGraph(e);

            if (graph != null) {
                graph.removeCellsFromParent();
            }
        }

    }

    /**
     * The type Update group bounds action.
     */
    public static class UpdateGroupBoundsAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = -4718086600089409092L;

        /**
         * Instantiates a new Update group bounds action.
         *
         * @param name the name
         */
        public UpdateGroupBoundsAction(String name) {
            super(name);
        }

        /**
         * Gets group border.
         *
         * @param graph the graph
         * @return the group border
         */
        protected int getGroupBorder(mxGraph graph) {
            return 2 * graph.getGridSize();
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            mxGraph graph = getGraph(e);

            if (graph != null) {
                graph.updateGroupBounds(null, getGroupBorder(graph));
            }
        }

    }

    /**
     * The type Layer action.
     */
    public static class LayerAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = 562519299806253741L;

        /**
         * Instantiates a new Layer action.
         *
         * @param name the name
         */
        public LayerAction(String name) {
            super(name);
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            mxGraph graph = getGraph(e);

            if (graph != null) {
                boolean toBack = getValue(Action.NAME).toString()
                        .equalsIgnoreCase("toBack");
                graph.orderCells(toBack);
            }
        }

    }

    public static class ConnectableAction extends AbstractAction {

        private static final long serialVersionUID = 386944626580701571L;
        private List<JToggleButton> buttonList = new ArrayList<>();
        public ConnectableAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            Object source = e.getSource();

            if (source instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) source;
                graphComponent.setConnectable(!graphComponent.isConnectable());
                for (JToggleButton button : buttonList) {
                    button.setSelected(graphComponent.isConnectable());
                }
            } else {
                System.out.println(source.getClass().getName());
            }
        }

        public void addToggleButton(JToggleButton toggleButton) {
            buttonList.add(toggleButton);
        }
    }

    /**
     * The type Fold action.
     */
    public static class FoldAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = 4078517503905239901L;

        /**
         * Instantiates a new Fold action.
         *
         * @param name the name
         */
        public FoldAction(String name) {
            super(name);
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            mxGraph graph = getGraph(e);

            if (graph != null) {
                boolean collapse = getValue(Action.NAME).toString()
                        .equalsIgnoreCase("collapse");
                graph.foldCells(collapse);
            }
        }

    }

    /**
     * The type Drill action.
     */
    public static class DrillAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = 5464382323663870291L;

        /**
         * Instantiates a new Drill action.
         *
         * @param name the name
         */
        public DrillAction(String name) {
            super(name);
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            mxGraph graph = getGraph(e);

            if (graph != null) {
                String name = getValue(Action.NAME).toString();

                if (name.equalsIgnoreCase("enterGroup")) {
                    graph.enterGroup();
                } else if (name.equalsIgnoreCase("exitGroup")) {
                    graph.exitGroup();
                } else {
                    graph.home();
                }
            }
        }

    }

    /**
     * The type Zoom action.
     */
    public static class ZoomAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = -7500195051313272384L;

        /**
         * Instantiates a new Zoom action.
         *
         * @param name the name
         */
        public ZoomAction(String name) {
            super(name);
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            Object source = e.getSource();

            if (source instanceof mxGraphComponent) {
                String name = getValue(Action.NAME).toString();
                mxGraphComponent graphComponent = (mxGraphComponent) source;

                if (name.equalsIgnoreCase("zoomIn")) {
                    graphComponent.zoomIn();
                } else if (name.equalsIgnoreCase("zoomOut")) {
                    graphComponent.zoomOut();
                } else {
                    graphComponent.zoomActual();
                }
            }
        }

    }

    /**
     * The type Select action.
     */
    public static class SelectAction extends AbstractAction {

        /**
         *
         */
        private static final long serialVersionUID = 6501585024845668187L;

        /**
         * Instantiates a new Select action.
         *
         * @param name the name
         */
        public SelectAction(String name) {
            super(name);
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            mxGraph graph = getGraph(e);

            if (graph != null) {
                String name = getValue(Action.NAME).toString();

                if (name.equalsIgnoreCase("selectAll")) {
                    graph.selectAll();
                } else if (name.equalsIgnoreCase("selectNone")) {
                    graph.clearSelection();
                } else if (name.equalsIgnoreCase("selectNext")) {
                    graph.selectNextCell();
                } else if (name.equalsIgnoreCase("selectPrevious")) {
                    graph.selectPreviousCell();
                } else if (name.equalsIgnoreCase("selectParent")) {
                    graph.selectParentCell();
                } else if (name.equalsIgnoreCase("vertices")) {
                    graph.selectVertices();
                } else if (name.equalsIgnoreCase("edges")) {
                    graph.selectEdges();
                } else {
                    graph.selectChildCell();
                }
            }
        }

    }

}
